package org.dalmatian.common.encrypt.interceptor;

import cn.hutool.core.util.RandomUtil;
import org.dalmatian.common.core.utils.JsonUtils;
import org.dalmatian.common.core.utils.SolonUtils;
import org.dalmatian.common.core.utils.StringUtils;
import org.dalmatian.common.encrypt.annotation.ApiEncrypt;
import org.dalmatian.common.encrypt.properties.ApiDecryptProperties;

import org.dalmatian.common.encrypt.utils.EncryptUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import jodd.net.HttpMethod;
import org.noear.solon.annotation.Condition;

import org.noear.solon.core.aspect.Interceptor;
import org.noear.solon.core.aspect.Invocation;
import org.noear.solon.core.handle.Context;


/**
 * Crypto 过滤器
 *
 * @author wdhcr
 */

@Condition(onProperty = "${api-decrypt.enabled} == true")
public class CryptoInterceptor implements Interceptor {



    private final ApiDecryptProperties properties = SolonUtils.getBean(ApiDecryptProperties.class);

    /**
     * 获取加密内容
     *
     * @param publicKey       RSA公钥 (用于加密 AES 秘钥)
     * @param headerFlag      请求头标志
     * @return 加密内容
     * @throws IOException
     */
    public String getEncryptContent(Context context, String publicKey, String headerFlag,Object result) throws IOException {
        // 生成秘钥
        String aesPassword = RandomUtil.randomString(32);
        // 秘钥使用 Base64 编码
        String encryptAes = EncryptUtils.encryptByBase64(aesPassword);
        // Rsa 公钥加密 Base64 编码
        String encryptPassword = EncryptUtils.encryptByRsa(encryptAes, publicKey);

        // 设置响应头
        // vue版本需要设置
         context.headerAdd("Access-Control-Expose-Headers", headerFlag);
         context.headerAdd("Access-Control-Allow-Origin", "*");
         context.headerAdd("Access-Control-Allow-Methods", "*");
         context.headerAdd(headerFlag, encryptPassword);
         context.charset(StandardCharsets.UTF_8.toString());
        // 获取原始内容
         String originalBody = JsonUtils.toJsonString(result);
        // 对内容进行加密
        return EncryptUtils.encryptByAes(originalBody, aesPassword);
    }

    @Override
    public Object doIntercept(Invocation inv) throws Throwable {
        Context ctx = Context.current();
        ApiEncrypt anno = inv.getMethodAnnotation(ApiEncrypt.class);
        if (anno == null) {
            return inv.invoke();
        } else if (HttpMethod.PUT.equalsName(ctx.method()) || HttpMethod.POST.equalsName(
            ctx.method())) {
            // 是否存在加密标头
            String headerValue = ctx.header(properties.getHeaderFlag());
            if (StringUtils.isNotBlank(headerValue)) {
                // 请求解密
                Object result =  inv.invoke();
                if (anno.response()) {
                    return getEncryptContent(ctx, properties.getPublicKey(),
                        properties.getHeaderFlag(),result);
                }
                return result;
            }
             return inv.invoke();
        }else {
            return inv.invoke();
        }
    }

}
